/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package za.co.pas.business.data;

import java.io.Serializable;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import za.co.pas.business.constant.Constant;
import za.co.pas.business.data.audit.Person_AUDIT;

/**
 *
 * @author alabuschagne
 */
@Entity
public class Person implements Serializable
{

    private static final long serialVersionUID = 1L;
    private Long id;
    private String firstName = "";
    private String surName = "";
    private Address streetAddress;
    private Address postalAddress;
    private String tel = "";
    private String cel = "";
    private String fax = "";
    private String email = "";
    private boolean processed = false;
    private List<Person_AUDIT> personList = new LinkedList<Person_AUDIT>();

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId()
    {
        return id;
    }

    public void setId(Long id)
    {
        this.id = id;
    }

    @Override
    public int hashCode()
    {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object)
    {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Person))
        {
            return false;
        }
        Person other = (Person) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id)))
        {
            return false;
        }
        return true;
    }

    @Override
    public String toString()
    {
        return "za.co.pas.spaceandtime.data.Person[id=" + id + "]";
    }

    /**
     * @return the firstName
     */
    public String getFirstName()
    {
        return firstName;
    }

    /**
     * @param firstName the firstName to set
     */
    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }

    /**
     * @return the surName
     */
    public String getSurName()
    {
        return surName;
    }

    /**
     * @param surName the surName to set
     */
    public void setSurName(String surName)
    {
        this.surName = surName;
    }

    /**
     * @return the streetAddress
     */
    @OneToOne
    public Address getStreetAddress()
    {
        return streetAddress;
    }

    /**
     * @param streetAddress the streetAddress to set
     */
    public void setStreetAddress(Address streetAddress)
    {
        this.streetAddress = streetAddress;
    }

    /**
     * @return the postalAddress
     */
    @OneToOne
    public Address getPostalAddress()
    {
        return postalAddress;
    }

    /**
     * @param postalAddress the postalAddress to set
     */
    public void setPostalAddress(Address postalAddress)
    {
        this.postalAddress = postalAddress;
    }

    /**
     * @return the tel
     */
    public String getTel()
    {
        return tel;
    }

    /**
     * @param tel the tel to set
     */
    public void setTel(String tel)
    {
        this.tel = tel;
    }

    /**
     * @return the cel
     */
    public String getCel()
    {
        return cel;
    }

    /**
     * @param cel the cel to set
     */
    public void setCel(String cel)
    {
        this.cel = cel;
    }

    /**
     * @return the fax
     */
    public String getFax()
    {
        return fax;
    }

    /**
     * @param fax the fax to set
     */
    public void setFax(String fax)
    {
        this.fax = fax;
    }

    /**
     * @return the email
     */
    public String getEmail()
    {
        return email;
    }

    /**
     * @param email the email to set
     */
    public void setEmail(String email)
    {
        this.email = email;
    }

    public boolean check(Person otherPerson)
    {
        if (otherPerson == null)
        {
            return false;
        }

        boolean found = ((Constant.stringCompare(firstName, otherPerson.getFirstName()))
                && (Constant.stringCompare(surName, otherPerson.getSurName()))
                && (Constant.stringCompare(tel, otherPerson.getTel()))
                && (Constant.stringCompare(cel, otherPerson.getCel()))
                && (Constant.stringCompare(fax, otherPerson.getFax()))
                && (Constant.stringCompare(email, otherPerson.getEmail())));
        if (!found)
        {
            return false;
        }
        else if ((streetAddress == null) && (otherPerson.getStreetAddress() != null))
        {
            return false;
        }
        else if ((streetAddress != null) && (!streetAddress.check(otherPerson.getStreetAddress())))
        {
            return false;
        }
        else if ((postalAddress == null) && (otherPerson.getPostalAddress() != null))
        {
            return false;
        }
        else if ((postalAddress != null) && (!postalAddress.check(otherPerson.getPostalAddress())))
        {
            return false;
        }
        return true;
    }

    @Override
    public Person clone()
    {
        Person p = new Person();
        p.setCel(cel);
        p.setEmail(email);
        p.setFax(fax);
        p.setFirstName(firstName);
        p.setId(id);
        p.setPostalAddress(postalAddress.clone());
        p.setStreetAddress(streetAddress.clone());
        p.setSurName(surName);
        p.setTel(tel);
        return p;
    }

    /**
     * @return the processed
     */
    @Transient
    public boolean isProcessed()
    {
        return processed;
    }

    /**
     * @param processed the processed to set
     */
    public void setProcessed(boolean processed)
    {
        this.processed = processed;
    }

    public boolean set(Company company, UserLoginDetails uld, Person person)
    {
        boolean updated = false;
        if (person == null)
        {
            return updated;
        }
        if (!Constant.stringCompare(getCel(), person.getCel()))
        {
            makeAudit(company, "CEL", uld, getCel(), person.getCel());
            setCel(person.getCel());
            updated = true;
        }
        if (!Constant.stringCompare(getEmail(), person.getEmail()))
        {
            makeAudit(company, "EMAIL", uld, getEmail(), person.getEmail());
            setEmail(person.getEmail());
            updated = true;
        }
        if (!Constant.stringCompare(getFax(), person.getFax()))
        {
            makeAudit(company, "FAX", uld, getFax(), person.getFax());
            setFax(person.getFax());
            updated = true;
        }
        if (!Constant.stringCompare(getFirstName(), person.getFirstName()))
        {
            makeAudit(company, "FIRSTNAME", uld, getFirstName(), person.getFirstName());
            setFirstName(person.getFirstName());
            updated = true;
        }
        if (!Constant.stringCompare(getSurName(), person.getSurName()))
        {
            makeAudit(company, "SURNAME", uld, getSurName(), person.getSurName());
            setSurName(person.getSurName());
            updated = true;
        }
        if (!Constant.stringCompare(getTel(), person.getTel()))
        {
            makeAudit(company, "TEL", uld, getTel(), person.getTel());
            setTel(person.getTel());
            updated = true;
        }
        Address sa = getStreetAddress();
        boolean update = false;
        if ((sa == null) && (person.getStreetAddress() != null))
        {
            sa = new Address();
            update = true;
        }
        else if ((sa != null) && (person.getStreetAddress() == null))
        {
            update = true;
        }
        else if ((sa != null) && (person.getStreetAddress() != null))
        {
            update = !sa.check(person.getStreetAddress());
        }
        if (update)
        {
            updated |= sa.set(company,uld, person.getStreetAddress());
        }
        Address pa = getPostalAddress();
        update = false;
        if ((pa == null) && (person.getPostalAddress() != null))
        {
            pa = new Address();
            update = true;
        }
        else if ((pa != null) && (person.getPostalAddress() == null))
        {
            update = true;
        }
        else if ((pa != null) && (person.getPostalAddress() != null))
        {
            update = !pa.check(person.getPostalAddress());
        }
        if (update)
        {
            updated |= pa.set(company,uld, person.getPostalAddress());
        }
        return updated;
    }

    private void makeAudit(Company company, String colName, UserLoginDetails uld, Object oldValue, Object newValue)
    {
        Person_AUDIT ca = new Person_AUDIT();
        ca.setColName(colName);
        ca.setChangedAt(Calendar.getInstance());
        ca.setChangedBy(uld);
        if (getId() != null)
        {
            ca.setCompany(company);
        }
        else
        {
            ca.setCompany(null);//new
        }
        ca.setLongId(getId());
        if (newValue != null)
        {
            ca.setNewValue(newValue.toString());
        }
        else
        {
            ca.setNewValue(null);
        }

        if (oldValue != null)
        {
            ca.setOldValue(oldValue.toString());
        }
        else
        {
            ca.setOldValue(null);
        }
        add(ca);
    }

    /**
     * @return the personList
     */
    @Transient
    public List<Person_AUDIT> getPersonList()
    {
        return personList;
    }

    /**
     * @param personList the personList to set
     */
    public void setPersonList(List<Person_AUDIT> personList)
    {
        this.personList = personList;
    }

    private void add(Person_AUDIT ca)
    {
        if (personList == null)
        {
            personList = new LinkedList<Person_AUDIT>();
        }
        personList.add(ca);
    }

    public String logPrint(int level)
    {
        StringBuilder tab = new StringBuilder();
        for(int i = 0; i < level; i++)
        {
            tab.append("\t");
        }
        StringBuilder sb = new StringBuilder(tab.toString());
        sb.append("PERSON\n");
        sb.append(tab.toString());
        sb.append("ID: \t");
        sb.append(id);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("FirstName: \t");
        sb.append(firstName);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("SurName: \t");
        sb.append(surName);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Tel: \t");
        sb.append(tel);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Cel: \t");
        sb.append(cel);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Fax: \t");
        sb.append(fax);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Email: \t");
        sb.append(email);
        int l2 = level + 1;

        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Street Address: \t");
        sb.append(streetAddress.logPrint(l2));
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Postal Address: \t");
        sb.append(postalAddress.logPrint(l2));
        return sb.toString();
    }
}
